package com.sieman.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.channels.FileChannel;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;


/**
 * 
 * @ClassName: DC
 * @Description: 数据转换工具类
 * @author  kangjie1209@126.com
 * @date 2016年12月7日 上午9:55:46
 *
 */
public class DC {

	public static final byte SUCCESS = 0x40;
	public static final byte FAILD = (byte) 0x80;

	public static String bToHS(byte src) {
		String hv = Integer.toHexString(src & 0xFF);
		String prx = "";
		if (hv.length() < 2) {
			prx = "0";
		}
		return prx + hv;
	}

	public static String bsToHS(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder("");
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			String hv = bToHS(src[i]);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}

	// 取高位
	public static byte HighBit3(int i) {
		// return i >> 16;
		return (byte) ((i >> 24) & 0xFF);
	}

	// 取高位
	public static byte HighBit2(int i) {
		// return i >> 16;
		return (byte) ((i >> 16) & 0xFF);
	}

	// 取高位
	public static byte HighBit(int i) {
		// return i >> 16;
		return (byte) ((i >> 8) & 0xFF);
	}

	// 取低位
	public static byte LowBit(int i) {
		// return i & 0xFFFF;
		return (byte) (i & 0xFF);
	}

	/**
	 * Convert hex string to byte[]
	 * 
	 * @param hexString
	 *            the hex string
	 * @return byte[]
	 */
	public static byte[] hSToBs(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	/**
	 * Convert char to byte
	 * 
	 * @param c
	 *            char
	 * @return byte
	 */
	public static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	/**
	 * 
	 * @param i
	 *            要操作的数
	 * @param pos
	 *            第几位
	 * @return 把 i 的第pos 位变为0后的值
	 */
	public static int do0(int i, int pos) {
		int src = Integer.MAX_VALUE ^ (1 << (pos - 1));
		return i & src;
	}

	/**
	 * 
	 * @param i要操作的数
	 * @param pos
	 *            第几位
	 * @return 把 i 的第pos 位变为1后的值
	 */
	public static int do1(int i, int pos) {
		return i | (1 << pos - 1);
	}

	/**
	 * 转换有效路灯组
	 * 
	 * @param list
	 *            对所有元素进行转换，8个灯转为一个字节
	 * @return 最高的灯组号在最高位 <br>
	 *         第一个字节<br>
	 *         0=1表示该策略对1#灯有效<br>
	 *         1=1表示该策略对2#灯有效<br>
	 *         .....<br>
	 *         7=1表示该策略对8#灯有效<br>
	 *         ex. 2、3、8号灯有效，则为10000110，转为字节为0x86<br>
	 *         第二个字节对应于9#~16#灯<br>
	 *         ........<br>
	 *         第50个字节对应于392#~400#灯<br>
	 */
	public static byte[] convertLampSN(List<Integer> list) {
		byte[] ss = new byte[50];
		if (list == null || list.size() == 0) {
			return ss;
		}
		Collections.sort(list);
		int indexForList = list.size() - 1;
		for (int i = 1; i <= ss.length; i++) {
			int base = 0;
			for (int j = 0; j < 8; j++) {
				int index = (ss.length * 8) - (i - 1) * 8 - j;
				if (indexForList >= 0
						&& index == list.get(indexForList).intValue()) {
					indexForList--;
					base = do1(base, 8 - j);
				}
			}
			ss[ss.length - i] = DC.LowBit(base);
		}
		return ss;
	}

	/**
	 * 转换有效回路组号，回路号对应从低位到高位的顺序
	 * 
	 * @param list
	 *            只取第一个元素进行转换
	 * @return 十六进制字节 ：<br>
	 *         1号回路有效，则为0000 0001<br>
	 *         3号8号回路有效，则为1000 0100
	 */
	public static byte convertCircuitSN(List<Integer> list) {
		byte ss = 0;
		if (list == null || list.size() == 0) {
			return ss;
		}
		int listSize = list.size();
		int indexForList = 0;
		int base = 0;
		for (int i = 1; i < 9; i++) {
			if (indexForList < listSize && i == list.get(indexForList)) {
				indexForList++;
				base = do1(base, i);
			}
		}
		ss = DC.LowBit(base);
		return ss;
	}

	/**
	 * Time 2014-10-01
	 * 
	 * @param time
	 *            0x14 10 01 00 00 00
	 */
	public static byte[] convertDateTBytes(String time) {
		byte[] result = new byte[6];
		String t = time.replace("-", "").substring(2);
		for (int i = 0; i < t.length() / 2; i++) {
			result[i] = (byte) Integer.parseInt(t.substring(i * 2, i * 2 + 2));
		}
		return result;
	}

	/**
	 * 字符串转换成十六进制字符串
	 */

	public static String str2HexStr(String str) {

		char[] chars = "0123456789ABCDEF".toCharArray();
		StringBuilder sb = new StringBuilder("");
		byte[] bs = str.getBytes();
		int bit;
		for (int i = 0; i < bs.length; i++) {
			bit = (bs[i] & 0x0f0) >> 4;
			sb.append(chars[bit]);
			bit = bs[i] & 0x0f;
			sb.append(chars[bit]);
		}
		return sb.toString();
	}

	/**
	 * 
	 * 十六进制转换字符串
	 */

	public static String hexStr2Str(String hexStr) {
		String str = "0123456789ABCDEF";
		char[] hexs = hexStr.toCharArray();
		byte[] bytes = new byte[hexStr.length() / 2];
		int n;
		for (int i = 0; i < bytes.length; i++) {
			n = str.indexOf(hexs[2 * i]) * 16;
			n += str.indexOf(hexs[2 * i + 1]);
			bytes[i] = (byte) (n & 0xff);
		}
		return new String(bytes);
	}

	/**
	 * String的字符串转换成unicode的String
	 */
	public static String str2Unicode(String strText) throws Exception {
		char c;
		String strRet = "";
		int intAsc;
		String strHex;
		for (int i = 0; i < strText.length(); i++) {
			c = strText.charAt(i);
			intAsc = (int) c;
			strHex = Integer.toHexString(intAsc);
			if (intAsc > 128) {
				strRet += "//u" + strHex;
			} else {
				// 低位在前面补00
				strRet += "//u00" + strHex;
			}
		}
		return strRet;
	}

	/**
	 * unicode的String转换成String的字符串
	 */
	public static String unicode2Str(String hex) {
		int t = hex.length() / 6;
		StringBuilder str = new StringBuilder();
		for (int i = 0; i < t; i++) {
			String s = hex.substring(i * 6, (i + 1) * 6);
			// 高位需要补上00再转
			String s1 = s.substring(2, 4) + "00";
			// 低位直接转
			String s2 = s.substring(4);
			// 将16进制的string转为int
			int n = Integer.valueOf(s1, 16) + Integer.valueOf(s2, 16);
			// 将int转换为字符
			char[] chars = Character.toChars(n);
			str.append(new String(chars));
		}
		return str.toString();
	}

	/**
	 * 将一个单字节的byte转换成32位的int
	 * 
	 * @param b
	 *            byte
	 * @return convert result
	 */
	public static int unsignedByteToInt(byte b) {
		return (int) b & 0xFF;
	}

	/**
	 * 将一个单字节的Byte转换成十六进制的数
	 * 
	 * @param b
	 *            byte
	 * @return convert result
	 */
	public static String byteToHex(byte b) {
		int i = b & 0xFF;
		return Integer.toHexString(i);
	}

	public static int bsToInt32(byte bH, byte bL) {
		byte[] b = {bH,bL};
		return byte2ToUnsignedShort(b, 0);
	}

	public static long unsigned4BytesToInt(byte b1, byte b2, byte b3, byte b4) {
		byte[] b = { b1, b2, b3, b4 };
		return unsigned4BytesToInt(b, 0);
	}

	/**
	 * 将一个4byte的数组转换成32位的int
	 * 
	 * @param buf
	 *            bytes buffer
	 * @param byte[]中开始转换的位置
	 * @return convert result
	 */
	public static long unsigned4BytesToInt(byte[] buf, int pos) {
		int firstByte = 0;
		int secondByte = 0;
		int thirdByte = 0;
		int fourthByte = 0;
		int index = pos;
		firstByte = (0x000000FF & ((int) buf[index]));
		secondByte = (0x000000FF & ((int) buf[index + 1]));
		thirdByte = (0x000000FF & ((int) buf[index + 2]));
		fourthByte = (0x000000FF & ((int) buf[index + 3]));
		index = index + 4;
		return ((long) (firstByte << 24 | secondByte << 16 | thirdByte << 8 | fourthByte)) & 0xFFFFFFFFL;
	}

	/**
	 * 将16位的short转换成byte数组
	 * 
	 * @param s
	 *            short
	 * @return byte[] 长度为2
	 * */
	public static byte[] shortToByteArray(short s) {
		byte[] targets = new byte[2];
		for (int i = 0; i < 2; i++) {
			int offset = (targets.length - 1 - i) * 8;
			targets[i] = (byte) ((s >>> offset) & 0xff);
		}
		return targets;
	}

	/**
	 * 将32位整数转换成长度为4的byte数组
	 * 
	 * @param s
	 *            int
	 * @return byte[]
	 * */
	public static byte[] intToByteArray(int s) {
		byte[] targets = new byte[2];
		for (int i = 0; i < 4; i++) {
			int offset = (targets.length - 1 - i) * 8;
			targets[i] = (byte) ((s >>> offset) & 0xff);
		}
		return targets;
	}

	/**
	 * long to byte[]
	 * 
	 * @param s
	 *            long
	 * @return byte[]
	 * */
	public static byte[] longToByteArray(long s) {
		byte[] targets = new byte[2];
		for (int i = 0; i < 8; i++) {
			int offset = (targets.length - 1 - i) * 8;
			targets[i] = (byte) ((s >>> offset) & 0xff);
		}
		return targets;
	}

	/** 32位int转byte[] */
	public static byte[] int2byte(int res) {
		byte[] targets = new byte[4];
		targets[0] = (byte) (res & 0xff);// 最低位
		targets[1] = (byte) ((res >> 8) & 0xff);// 次低位
		targets[2] = (byte) ((res >> 16) & 0xff);// 次高位
		targets[3] = (byte) (res >>> 24);// 最高位,无符号右移。
		return targets;
	}
	
	
	public static byte[] LongToBytes(long values,int length) {  
	     byte[] buffer = new byte[length]; 
	     for (int i = 0; i < length; i++) {   
	          int offset = length * 8 - (i + 1) * 8;    
	          buffer[i] = (byte) ((values >> offset) & 0xff); 
	      }
	     return buffer;  
	}
	
	
	public static long BytesToLong(byte[] buffer,int length) {   
		   long  values = 0;
		   for (int i = 0; i < length; i++) {    
		       values <<= 8; values|= (buffer[i] & 0xff);   
		   }   
		   return values;  
	} 
	
	
	public static long byteArrayToLong(byte[] bytes) {
        long result = 0;
        int len = bytes.length;
        if (len == 1) {
            byte ch = (byte) (bytes[0] & 0xff);
            result = ch;
        } else if (len == 2) {
            int ch1 = bytes[0] & 0xff;
            int ch2 = bytes[1] & 0xff;
            result = (short) ((ch1 << 8) | (ch2 << 0));
        } else if (len == 4) {
            int ch1 = bytes[0] & 0xff;
            int ch2 = bytes[1] & 0xff;
            int ch3 = bytes[2] & 0xff;
            int ch4 = bytes[3] & 0xff;
            result = (int) ((ch1 << 24) | (ch2 << 16) | (ch3 << 8) | (ch4 << 0));
        } else if (len == 8) {
            long ch1 = bytes[0] & 0xff;
            long ch2 = bytes[1] & 0xff;
            long ch3 = bytes[2] & 0xff;
            long ch4 = bytes[3] & 0xff;
            long ch5 = bytes[4] & 0xff;
            long ch6 = bytes[5] & 0xff;
            long ch7 = bytes[6] & 0xff;
            long ch8 = bytes[7] & 0xff;
            result = (ch1 << 56) | (ch2 << 48) | (ch3 << 40) | (ch4 << 32) | (ch5 << 24) | (ch6 << 16) | (ch7 << 8) | (ch8 << 0);
        }
        return result;
    }
	
	  //高位在前，低位在后  
    public static byte[] int2bytes(int num){  
        byte[] result = new byte[4];  
        result[0] = (byte)((num >>> 24) & 0xff);//说明一  
        result[1] = (byte)((num >>> 16)& 0xff );  
        result[2] = (byte)((num >>> 8) & 0xff );  
        result[3] = (byte)((num >>> 0) & 0xff );  
        return result;  
    }  
      
    //高位在前，低位在后  
    public static int bytes2int(byte[] bytes){  
        int result = 0;  
        if(bytes.length == 4){  
            int a = (bytes[0] & 0xff) << 24;//说明二  
            int b = (bytes[1] & 0xff) << 16;  
            int c = (bytes[2] & 0xff) << 8;  
            int d = (bytes[3] & 0xff);  
            result = a | b | c | d;  
        }  
        return result;  
    }  

	/**
	 * 将长度为2的byte数组转换为16位int
	 * 
	 * @param res
	 *            byte[]
	 * @return int
	 * */
	public static int byte2Int16(byte[] res) {
		return (res[0] & 0xff) | ((res[1] << 8) & 0xff00); // | 表示安位或
	}

	/**
	 * 将byte转换为16位int
	 * 
	 * @param res
	 *            
	 * @return int
	 * */
	public static int byte2Int16(byte res) {
		return (res & 0xff) ; // | 表示安位或
	}

	/**
	 * byte数组转换为无符号short整数
	 * 
	 * @param bytes
	 *            byte数组
	 * @param off
	 *            开始索引
	 * @return short整数
	 */
	public static int byte2ToUnsignedShort(byte[] bytes, int off) {
		int high = bytes[off];
		int low = bytes[off + 1];
		return (high << 8 & 0xFF00) | (low & 0xFF);
	}

	public String binaryString(byte b) {
		return Integer.toBinaryString(b & 0xFF);
	}

	private static final int[] DAY_OF_WEEK = { 0, 1, 2, 3, 4, 5, 6 };

	public static int getDayOfWeek(Calendar now) {
		int day = now.get(Calendar.DAY_OF_WEEK);
		return DAY_OF_WEEK[day - 1];
	}

	public static boolean isLegalHead(byte[] head) {
		if (head.length >= 4) {
			if (head[0] == (byte) 0xD5 && head[1] == (byte) 0xC8
					&& head[2] == (byte) 0xD5 && head[3] == (byte) 0xC8) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 
	 * @Title: isSensorLegalHead
	 * @Description:传感器心跳包 
	 * @param head
	 * @return boolean
	 * @author  kangjie1209@126.com
	 * @date 2016年12月7日 上午9:35:24
	 */
	public static boolean isSensorLegalHead(byte[] head) {
		if (head.length >= 8) {
			if (head[0] == (byte) 0x68  && head[7] == (byte) 0x68) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 当前时间是否处于限制的时间段
	 * 
	 * @param start
	 *            开始时间,格式为 小时:分钟
	 * @param end
	 *            结束时间,格式为 小时:分钟
	 * @return true-处于限定时间段内
	 */
	public static boolean isInlimitTimePeriod(String start, String end) {
		Calendar now = Calendar.getInstance();
		now.setTimeInMillis(System.currentTimeMillis());
		String[] startTime = start.split(":");
		Calendar startCal = Calendar.getInstance();
		startCal.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH),
				now.get(Calendar.DAY_OF_MONTH), Integer.parseInt(startTime[0]),
				Integer.parseInt(startTime[1]));
		String[] endTime = end.split(":");
		Calendar endCal = Calendar.getInstance();
		endCal.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH),
				now.get(Calendar.DAY_OF_MONTH), Integer.parseInt(endTime[0]),
				Integer.parseInt(endTime[1]));
		if (now.compareTo(startCal) >= 0 && now.compareTo(endCal) <= 0) {
			return true;
		}
		return false;
	}
	
	
	//java 合并两个byte数组
	public static byte[] byteMerger(byte[] byte_1, byte[] byte_2){
		byte[] byte_3 = new byte[byte_1.length+byte_2.length];
		System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
		System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
		return byte_3;
	}

	
	
	public static String getRunPath(Class<?> cls){
		// 检查用户传入的参数是否为空
		if (cls == null)
			throw new java.lang.IllegalArgumentException("参数不能为空！");
		ClassLoader loader = cls.getClassLoader();
		// 获得类的全名，包括包名
		String clsName = cls.getName() + ".class";
		// 获得传入参数所在的包
		Package pack = cls.getPackage();
		String path = "";
		// 如果不是匿名包，将包名转化为路径
		if (pack != null) {
			String packName = pack.getName();
			// 此处简单判定是否是Java基础类库，防止用户传入JDK内置的类库
			if (packName.startsWith("java.") || packName.startsWith("javax."))
				throw new java.lang.IllegalArgumentException("不要传送系统类！");
			// 在类的名称中，去掉包名的部分，获得类的文件名
			clsName = clsName.substring(packName.length() + 1);
			// 判定包名是否是简单包名，如果是，则直接将包名转换为路径，
			if (packName.indexOf(".") < 0)
				path = packName + "/";
			else {// 否则按照包名的组成部分，将包名转换为路径
				int start = 0, end = 0;
				end = packName.indexOf(".");
				while (end != -1) {
					path = path + packName.substring(start, end) + "/";
					start = end + 1;
					end = packName.indexOf(".", start);
				}
				path = path + packName.substring(start) + "/";
			}
		}
		// 调用ClassLoader的getResource方法，传入包含路径信息的类文件名
		java.net.URL url = loader.getResource(path + clsName);
		// 从URL对象中获取路径信息
		String realPath = url.getPath();
		// 去掉路径信息中的协议名"file:"
		int pos = realPath.indexOf("file:");
		if (pos > -1)
			realPath = realPath.substring(pos + 5);
		// 去掉路径信息最后包含类文件信息的部分，得到类所在的路径
		pos = realPath.indexOf(path + clsName);
		realPath = realPath.substring(0, pos - 1);
		// 如果类文件被打包到JAR等文件中时，去掉对应的JAR等打包文件名
		if (realPath.endsWith("!"))
			realPath = realPath.substring(0, realPath.lastIndexOf("/"));
		/*------------------------------------------------------------ 
		 ClassLoader的getResource方法使用了utf-8对路径信息进行了编码，当路径 
		  中存在中文和空格时，他会对这些字符进行转换，这样，得到的往往不是我们想要 
		  的真实路径，在此，调用了URLDecoder的decode方法进行解码，以便得到原始的 
		  中文及空格路径 
		-------------------------------------------------------------*/
		try {
			realPath = java.net.URLDecoder.decode(realPath, "utf-8");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return realPath;
	}
	public static void copyFile(File from, File to) {
		FileInputStream fi = null;
		FileOutputStream fo = null;
		FileChannel in = null;
		FileChannel out = null;
		try {
			fi = new FileInputStream(from);
			fo = new FileOutputStream(to);
			in = fi.getChannel();// 得到对应的文件通道
			out = fo.getChannel();// 得到对应的文件通道
			in.transferTo(0, in.size(), out);// 连接两个通道，并且从in通道读取，然后写入out通道
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				fi.close();
				in.close();
				fo.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static <T> boolean compare(T obj1, T obj2) throws Exception {

		if(obj1 == null || obj2 == null){
			if(obj1 == obj2){
				return true;
			}else{
				return false;
			}
		}
		// Map<String, String> result = new HashMap<String, String>();

		Field[] fs = obj1.getClass().getDeclaredFields();
		for (Field f : fs) {
			f.setAccessible(true);
			Object v1 = f.get(obj1);
			Object v2 = f.get(obj2);
			if (!equals(v1, v2)) {
				return false;
			}
			// result.put(f.getName(), String.valueOf(equals(v1, v2)));
		}
		return true;
	}

	public static boolean equals(Object obj1, Object obj2) {
		if (obj1 == obj2) {
			return true;
		}
		if (obj1 == null || obj2 == null) {
			return false;
		}
		return obj1.equals(obj2);
	}
	
	public static byte[] addCRC(byte[] data){
		byte[] result = new byte[data.length + 2];
		System.arraycopy(data, 0, result, 0, data.length);
		byte[] crc = getCRC(data);
		System.arraycopy(crc, 0, result, data.length, crc.length);
		return result;
	}
	
	public static byte[] getCRC(byte[] data) {
		int crcValue = 0xffff;
		for (int j = 0; j < data.length; j++) {
			crcValue ^= byte2Int16(data[j]);
			for (int i = 0; i < 8; i++) {
				int k = crcValue;
				crcValue = crcValue >> 1;
				if ((k & 0x01) == 1)
					crcValue ^= 0xa001;
			}
		}
		byte[] cRC16 = new byte[] { (byte) (crcValue & 0xff), (byte) (crcValue >> 8) };
		return cRC16;
	}


	public static boolean checkCRC(byte[] recs) {
		boolean result = false;
		byte[] data = new byte[recs.length - 2];
		System.arraycopy(recs, 0, data, 0, data.length);
//		System.out.println(bsToHS(recs));
		byte[] newCrc = getCRC(data);
//		System.out.println(bsToHS(newCrc));
		if (newCrc[0] == recs[recs.length - 2]
				&& newCrc[1] == recs[recs.length - 1]) {
			result = true;
		}
		return result;
	}
	public static void main(String[] args) {
		System.out.println(byte2ToUnsignedShort(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },5));
	}
}
